package org.logsin37.util.press.api


import org.logsin37.util.press.entity.TestReport
import org.logsin37.util.press.entity.TraceLog
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpMethod
import org.springframework.http.RequestEntity
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import org.springframework.web.client.RestTemplate

import java.util.concurrent.CountDownLatch
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicInteger

@RestController
@RequestMapping("/press-test")
class PressTestController {

    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/hello")
    ResponseEntity<String> hello() {
        return ResponseEntity.ok("hello");
    }

    @PostMapping("/do-test")
    ResponseEntity<TestReport> doTest(
            @RequestParam(required = false, defaultValue = "10") int concurrentCount,
            @RequestParam(required = false, defaultValue = "10") long seconds
    ) throws URISyntaxException {
        def executorService = Executors.newFixedThreadPool concurrentCount

        def headers = new HttpHeaders()
        def request = new RequestEntity<String>(null, headers, HttpMethod.GET, new URI("https://www.baidu.com"))

        List<TraceLog>[] traceLogGroup = new List<TraceLog>[concurrentCount]
        for(def i=0; i<concurrentCount; i++) {
            traceLogGroup[i] = new ArrayList<TraceLog>()
        }
        for(def x=0 ; x<seconds; x++) {
            boolean[] flag = new boolean[1]
            flag[0] = true
            CountDownLatch countDownLatch = new CountDownLatch(1)
            AtomicInteger idGenerator = new AtomicInteger(0)
            for(def i=0; i<concurrentCount; i++) {
                executorService.execute {
                    def tid = idGenerator.getAndIncrement()
                    countDownLatch.await()
                    def log = TraceLog.init(String.valueOf(tid))
                    try {
                        this.restTemplate.exchange(request, String.class)
                        log.success()
                    } catch(ex) {
                        ex.printStackTrace()
                        log.error(ex.getMessage())
                    }
                    traceLogGroup[tid].add log
                }
            }
            countDownLatch.countDown()
            try{
                Thread.sleep(1000)
            } catch(ex) {
                // ignore
            }
            flag[0] = false;
        }

        executorService.shutdownNow()
        ResponseEntity.ok TestReport.generateReport(request, concurrentCount, seconds, traceLogGroup)
    }

}
